﻿#pragma once

#include <vulkan/vulkan.hpp>
#include "Render/VulkanDescriptor/VulkanDescriptorLayout.h"
#include "Math/Math.h"

struct SPointLightDefferShadingFragmentPushConstant
{
    float ViewPos[3];  //camera position
    float Padding;
    float Position[3]; //light position
    float Radius; //light radius
    float ColorWithIntensity[4]; // light color multipled Intensity
    float ShadowBias;
};

struct SSpotLightDefferShadingFragmentPushConstant
{
    float ViewPos[3];  //camera position
    float Padding;
    float Position[3]; //light position 
    float ShadowBias;
    float ColorWithIntensity[4]; // light color multipled Intensity
    float LightVP[16]; //light view projection matrix

};

#define EngineCascadeNum 4
struct SDirectionalLightDefferShadingFragmentUniformBuffer
{
    SMatrix4x4 LightVP[EngineCascadeNum];

    //this is a single float , only use Vec4's X, the Y/Z/W is Padding
    // used to get the correct shadow map, the last one is 1.0
    SVec4 MaxDepths[EngineCascadeNum];
    SVec3 LightDirection; //normalized 
    float Padding;
    SVec3 LightColorWithIntensity;
    float Padding2;
    SVec3 ViewPos; //camera position
    float Padding3;
    float ShadowBias;
};

//场景渲染需要的全局变量
class CSceneGlobal
{
public:
    void Init();

    //网格数据的参数描述布局，目前只有一个缓冲区，含有一个 ModelMatrix
    SVulkanDescriptorLayout ModelDescriptorSetLayout;
    SVulkanDescriptorLayout BatchModelDescriptorSetLayout;

    //场景全局参数描述布局
    //包含了一个缓冲区， 用于存储相机位置等参数
    vk::DescriptorSetLayout SceneParameterLayout;

    //阴影贴图的采样器
    vk::Sampler ShadowMapSampler;

protected:
    void CreateModelDescriptorSetLayout();
    void CreateSceneParameterLayout();
    void CreateShadowMapSampler();

public:

protected:

public:
    //场景渲染的渲染通道
    vk::RenderPass SceneRenderPass;

    //延迟渲染着色阶段的描述布局
    SVulkanDescriptorLayout DefferShadingDescriptorSetLayout;

    //延迟渲染最终输出的图像的采样器
    vk::Sampler DefferRenderingOutputSampler;



    //点光源渲染阴影贴图阶段：
    struct SPointLightShadowMapBuffer
    {
        float ProjectionViewMatrix[16]; //光源的投影矩阵和视图矩阵
        float LightPosition[3]; //光源的世界坐标
    };
    vk::Format PointLightShadowMapImageFormat= vk::Format::eR32Sfloat;
    vk::RenderPass PointLightShadowMapRenderPass;
    SVulkanDescriptorLayout PointLightShadowMapDescriptorSetLayout;
    vk::PipelineLayout PointLightShadowMapPipelineLayout;
    vk::Pipeline PointLightShadowMapPipeline;
    vk::Extent2D PointLightShadowMapExtent; 

    //点光源延迟渲染阶段:
    SVulkanDescriptorLayout PointLightDefferShadingDescriptorSetLayout;
    vk::PipelineLayout PointLightDefferShadingPipelineLayout;
    vk::Pipeline PointLightDefferShadingPipeline;


    //聚光灯生成阴影贴图阶段：
    using SSpotLightShadowMapBuffer= SPointLightShadowMapBuffer;
    vk::Format SpotLightShadowMapImageFormat= vk::Format::eR32Sfloat;
    vk::RenderPass SpotLightShadowMapRenderPass;
    SVulkanDescriptorLayout SpotLightShadowMapDescriptorSetLayout;
    vk::PipelineLayout SpotLightShadowMapPipelineLayout;
    vk::Pipeline SpotLightShadowMapPipeline;
    vk::Extent2D SpotLightShadowMapExtent;

    //聚光灯延迟渲染阶段
    SVulkanDescriptorLayout SpotLightDefferShadingDescriptorSetLayout;
    vk::PipelineLayout SpotLightDefferShadingPipelineLayout;
    vk::Pipeline SpotLightDefferShadingPipeline;


    //平行光阴影贴图
    struct SDirectionalLightVertexPushConstant
    {
        SMatrix4x4 ProjectionViewMatrix; ////projection matrix * view matrix;
    };

    vk::Format DirectionalLightShadowMapImageFormat=  vk::Format::eD16Unorm;
    vk::Extent2D DirectionalLightShadowMapExtent= vk::Extent2D(2048,2048);
    vk::RenderPass DirectionalLightShadowMapRenderPass;
    SVulkanDescriptorLayout DirectionalLightShadowMapDescriptorSetLayout;
    vk::PipelineLayout DirectionalLightShadowMapPipelineLayout;
    vk::Pipeline DirectionalLightShadowMapPipeline;

    //平行光延迟渲染阶段
    static int GetCascadeNum() { return EngineCascadeNum; }
    SVulkanDescriptorLayout DirectionalLightDefferShadingDescriptorSetLayout;
    vk::PipelineLayout DirectionalLightDefferShadingPipelineLayout;
    vk::Pipeline DirectionalLightDefferShadingPipeline;

    //环境光照
    struct SAmbientLightDefferShadingFragmentPushConstant
    {
        SColor AmbientColorWithIntensity; // light color multipled Intensity
    };
    
    vk::PipelineLayout AmbientLightDefferShadingPipelineLayout;
    vk::Pipeline AmbientLightDefferShadingPipeline;
protected:
    void CreateSceneRenderPass();
    void CreateDefferShadingPipelines();

    void CreatePointLightShadowMapThings();
    void CreateSpotLightShadowMapThings();
    void CreateDirectionalLightShadowMapThings();

public:
    //抗锯齿
    vk::RenderPass AntiAliasingRenderPass;
    SVulkanDescriptorLayout AntiAliasingDescriptorSetLayout;
    vk::PipelineLayout AntiAliasingPipelineLayout;
    vk::Pipeline AntiAliasingPipeline;

protected:
    void CreateAntiAliasingPipeline();

};